<?php

namespace addons\cmstostatic\library;

use addons\cms\library\Service;
use addons\cmstostatic\model\Archives;
use addons\cmstostatic\model\Archives as ArchivesModel;
use addons\cmstostatic\model\Channel;
use addons\cmstostatic\model\Channel as ChannelModel;
use addons\cms\model\Fields;
use addons\cms\model\Modelx;
use addons\cmstostatic\model\Cmstostatic;
use think\addons\Controller;
use think\Config;
use think\Db;
use think\Request;


/**
 * cms静态资源生成器
 */
class Generator extends Controller
{
    var $static_root = '';
    var $domain = '';
    var $static_config = [];
    var $db_prefix = '';
    var $rootpath_length = 0;


    public function __construct(Request $request = null)
    {
        parent::__construct($request);

        // 限定管理员才能操作
        $admin_id = session('admin.id') ?: 0;
        if (!$admin_id) {
            $this->error("请管理员登录后再操作");
        }

        // 清除模板缓存
//        rmdirs(TEMP_PATH, false);

        $this->db_prefix = config('database.prefix');
        $this->rootpath_length = strlen(ROOT_PATH);

        // 生成静态的根路径
        $this->static_config = get_addon_config('cmstostatic');
        $this->static_root = ROOT_PATH . 'public' . DS; // 默认
//        var_dump($this->static_config);
        if(!empty($this->static_config['static_root'])){
            $this->static_root = ROOT_PATH . $this->static_config['static_root'] . DS;
            $this->makeDirectory($this->static_root);
        }

        // 开启生成手机站
        if(!empty($this->static_config['mobile_on'])){
            if(!empty($this->static_config['mobile_path'])){
                $this->static_root = $this->static_root . $this->static_config['mobile_path'] . DS;
                $this->makeDirectory($this->static_root);
            }
        }

        // 网站domain
        $this->domain = $this->request->domain();

        $config = get_addon_config('cms');
        // 设置替换字符串
        $cdnurl = Config::get('site.cdnurl');
        $this->view->replace('__ADDON__', $cdnurl . "/assets/addons/cms");

        // 设定模板目录 判断是否开启手机版
        if(empty($this->static_config['mobile_on'])){
            $this->view->engine->config('view_path', ADDON_PATH . 'cms' . DS . 'view' . DS . $config['theme'] . DS);
        }
        else{
            $this->view->engine->config('view_path', ADDON_PATH . 'cms' . DS . 'view' . DS . $config['theme'] . '_mobile' . DS);
        }

        // 赋值cms配置参数
        $this->view->assign('config', $config);
    }


    public function home()
    {
        $config = get_addon_config('cms');

        // 默认渲染栏目为空
        $this->view->assign('__CHANNEL__', null);
        // 定义CMS首页的URL
        \think\Config::set('cms.indexurl', addon_url('cms/index/index', [], false));

        //设置TKD
        Config::set('cms.title', $config['title'] ?: __('Home'));
        Config::set('cms.keywords', $config['keywords']);
        Config::set('cms.description', $config['description']);

//        $response = Response::create('/index','view')->getContent();

        $content = $this->view->fetch('/index');
        // 生成路径
        $static_path = $this->static_root . ($this->static_config['home_default'] ?: 'index.html');

        return $this->makeHtml($static_path,  $content);
    }


    public function channel($channel_id)
    {
        $config = get_addon_config('cms');
        $channel = ChannelModel::get($channel_id);
        $cmstostatic = Cmstostatic::get($channel_id);
        $cmstostaticRow = $cmstostatic->getData();

        // 动态访问
        if ($channel['type'] === 'link' || empty($cmstostaticRow['isstatic'])) {
            return 'redirect';
        }

        //加载模型数据
        $model = Modelx::get($channel['model_id']);

        $page_path = $cmstostaticRow['dirname'];
        if(!empty($this->static_config['mobile_on'])){ // 手机版路径
            $page_path = $this->static_config['mobile_path'] . '/' . $page_path;
        }

        // 生成静态分页处理
        $paginateConfig = [
            'type' => '\\addons\\cmstostatic\\library\\Bootstrap',
            'path' => '/' . $page_path,
            'channel_id' => $channel['id'],
            'listtype' => $cmstostaticRow['listtype'],
        ];

        if(0 == $channel['pagesize']){
            $this->error('分页数量大小不能为0');
        }

        $pageCount = ceil($channel['items'] / $channel['pagesize']) ?: 1;

        // 栏目分页循环开始 TODO 未处理栏目分页大数据情况 如一个栏目有1000+页面
        for($page=1; $page<=$pageCount; $page++){
            $paginateConfig['page'] = $page;
            $orderby = 'weigh DESC,id DESC';
            $orderway = 'desc';

            //加载列表数据
            $pageList = Archives::with(['channel', 'user'])->alias('a')
                ->where('a.status', 'normal')
                ->whereNull('a.deletetime')
                ->join($model['table'] . ' n', 'a.id=n.id', 'LEFT')
                ->field('a.*')
                ->field('id,content', true, config('database.prefix') . $model['table'], 'n')
                ->where(function ($query) use ($channel) {
                    $query->where(function ($query) use ($channel) {
                        if ($channel['listtype'] <= 2) {
                            $query->whereOr("channel_id", $channel['id']);
                        }
                        if ($channel['listtype'] == 1 || $channel['listtype'] == 3) {
                            $query->whereOr('channel_id', 'in', function ($query) use ($channel) {
                                $query->name("cms_channel")->where('parent_id', $channel['id'])->field("id");
                            });
                        }
                        if ($channel['listtype'] == 0 || $channel['listtype'] == 4) {
                            $childrenIds = \addons\cms\model\Channel::getChannelChildrenIds($channel['id'], false);
                            if ($childrenIds) {
                                $query->whereOr('channel_id', 'in', $childrenIds);
                            }
                        }
                    })
                        ->whereOr("(`channel_ids`!='' AND FIND_IN_SET('{$channel['id']}', `channel_ids`))");
                })
                ->where('model_id', $channel->model_id)
                ->order($orderby, $orderway)
                ->paginate($channel['pagesize'], $config['pagemode'] == 'simple', $paginateConfig);

            $fieldsContentList = Fields::getFieldsContentList('model', $model->id);
            foreach ($pageList as $index => $item) {
                Service::appendTextAttr($fieldsContentList, $item);
            }

            $fieldsContentList = Fields::getFieldsContentList('channel');
            Service::appendTextAttr($fieldsContentList, $channel);

            $this->view->assign("__FILTERLIST__", null);
            $this->view->assign("__ORDERLIST__", null);
            $this->view->assign("__PAGELIST__", $pageList);
            $this->view->assign("__CHANNEL__", $channel);

            //设置TKD
            Config::set('cms.title', isset($channel['seotitle']) && $channel['seotitle'] ? $channel['seotitle'] : $channel['name']);
            Config::set('cms.keywords', isset($channel['keywords']) && $channel['keywords'] ? $channel['keywords'] : $config['keywords']);
            Config::set('cms.description', isset($channel['description']) && $channel['description'] ? $channel['description'] : $config['description']);

            //读取模板
            $template = preg_replace('/\.html$/', '', $channel["{$channel['type']}tpl"]);
            if (!$template) {
                $this->error('请检查栏目是否配置相应的模板' . $template);
            }

            // 获取模板解析后的内容
            $content = $this->view->fetch('/' . $template);

            // 栏目列表 生成路径
            $static_path = $this->static_root . $cmstostaticRow['dirname'] . DS;

            // 栏目首页生成
            if(1 == $page){
                if(empty($cmstostaticRow['indextype'])){
                    // 生成伪静态同步的栏目首页名
                    $this->makeHtml($this->static_root . $channel['diyname'] . '.html',  $content);

                    // 栏目伪静态方式直接跳出
                    continue;
                }
                else{
                    // 需要目录时再创建
                    $this->makeDirectory($static_path);
                    // 生成目录名和默认文件index.html
                    $this->makeHtml($static_path . 'index.html',  $content);
                }
            }

            // 生成定义规则的html文件
            if(!empty($cmstostaticRow['listtype'])){
                $static_path .= str_replace(['{channel_id}', '{page}'], [$channel['id'], $page], $cmstostaticRow['listtype']);
            }
            else{
                $static_path .= 'list_' . $channel['id'] . '_' . $page .'.html';
            }

            $this->makeHtml($static_path,  $content);
        }
        // 栏目分页循环结束

        return true;
    }


    public function article($article_id)
    {
        $config = get_addon_config('cms');
        $archives = ArchivesModel::get($article_id, ['channel']);

        if (!$archives || ($archives['user_id'] != $this->auth->id && $archives['status'] != 'normal') || $archives['deletetime']) {
            $this->error(__('No specified article found'));
        }
        $channel = Channel::get($archives['channel_id']);
        if (!$channel) {
            $this->error(__('No specified channel found'));
        }

        $cmstostatic = Cmstostatic::get($archives['channel_id']);
        $cmstostaticRow = $cmstostatic->getData();

        // 栏目不生成静态
        if (empty($cmstostaticRow['isstatic'])) {
            return 'redirect';
        }

        $model = Modelx::get($channel['model_id'], [], true);
        if (!$model) {
            $this->error(__('No specified model found'));
        }
        $addon = db($model['table'])->where('id', $archives['id'])->find();
        if ($addon) {
            if ($model->fields) {
                $fieldsContentList = Fields::getFieldsContentList('model', $model->id);
                Service::appendTextAttr($fieldsContentList, $addon);
            }

            $archives->setData($addon);
        } else {
            $this->error(__('No specified addon article found'));
        }

        //PC支持内容分页 TODO 文章静态未支持分页
//        $page = (int)$this->request->request("page", 1);
//        $page = max(1, $page);
//        $contentArr = array_filter(explode("##pagebreak##", $archives->content));
//        $content = $contentArr ? (isset($contentArr[$page - 1]) ? $contentArr[$page - 1] : $contentArr[0]) : '';
//        $archives->content = $content . $archives->getPagerHTML($page, count($contentArr));

//        $archives->setInc("views", 1);
        $this->view->assign("__ARCHIVES__", $archives);
        $this->view->assign("__CHANNEL__", $channel);
        $this->view->assign("__MODEL__", $model);

        //设置TKD
        Config::set('cms.title', isset($archives['seotitle']) && $archives['seotitle'] ? $archives['seotitle'] : $archives['title']);
        Config::set('cms.keywords', isset($archives['keywords']) && $archives['keywords'] ? $archives['keywords'] : $config['keywords']);
        Config::set('cms.description', isset($archives['description']) && $archives['description'] ? $archives['description'] : $config['description']);

        //是否跳转链接
        if (isset($archives['outlink']) && $archives['outlink']) {
            return 'redirect';
        }

        $template = preg_replace('/\.html$/', '', $channel['showtpl']);
        if (!$template) {
            $this->error('请检查栏目是否配置相应的模板' . $template);
        }

//        $response = Response::create('/' . $template,'view')->getContent();
        $content = $this->view->fetch('/' . $template);

        // 生成路径
        $static_path = $this->static_root . $cmstostaticRow['dirname'] . DS;
        $this->makeDirectory($static_path);

        $static_path .= str_replace('{article_id}', $article_id, $cmstostaticRow['showtype']) ?: $article_id . '.html';

        return $this->makeHtml($static_path,  $content);
    }


    public function getChannelUrl($channel_id, $domain=false)
    {
        // todo 获取栏目生成url
        $channel = Channel::get($channel_id);
        $cmstostatic = Cmstostatic::get($channel_id);
        $cmstostaticRow = $cmstostatic->getData();

        if(!empty($cmstostaticRow['isstatic']) && !empty($cmstostaticRow['indextype'])){
            $url = '/';
            if(!empty($this->static_config['mobile_on'])){ // 手机版路径
                $url = '/' . $this->static_config['mobile_path'] . '/';
            }

            $url .= $cmstostaticRow['dirname'];

            if($domain){
                $url = $this->domain . $url;
            }
        }
        else{
            $url = $channel->getAttr('url');

            if($domain){
                $url = $channel->getAttr('fullurl');
            }
        }

        return $url;
    }


    public function getArticleUrl($article_id, $domain=false)
    {
        // TODO 获取文章生成url
        $article = Archives::get($article_id);
        $channel_id = $article->getData('channel_id');
        $cmstostatic = Cmstostatic::get($channel_id);
        $cmstostaticRow = $cmstostatic->getData();

        if(!empty($cmstostaticRow['isstatic'])){
            $url = '/';
            if(!empty($this->static_config['mobile_on'])){ // 手机版路径
                $url = '/' . $this->static_config['mobile_path'] . '/';
            }

            $url .= $cmstostaticRow['dirname'] . '/';
            $url .= str_replace('{article_id}', $article_id, $cmstostaticRow['showtype']) ?: $article_id . '.html';

            if($domain){
                $url = $this->domain . $url;
            }
        }
        else{
            $url = $article->getAttr('url');

            if($domain){
                $url =  $article->getAttr('fullurl');
            }
        }

        return $url;
    }


    private function makeHtml($fullpath, $content)
    {

        // TODO 此处记录生成文件记录 是随后删除的列表
        $path = substr($fullpath, $this->rootpath_length);
        $path = str_replace('\\', '/', $path);
        $path = addslashes($path);

        Db::execute("INSERT IGNORE INTO `" . $this->db_prefix . "cmstostatic_paths` (`path`) VALUES ('" . $path ."')");

        return file_put_contents($fullpath, $content);
    }


    private function makeDirectory($directory){
        if(!is_dir($directory)){
            return mkdir($directory, 0755, true);
        }
    }
}